/* 
 *  Syntelos XB
 *  Copyright (C) 2006 John Pritchard.
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License as
 *  published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 *  02111-1307 USA
 */

package syntelos.xb;

/** 
 * 
 * 
 * @author jdp
 */
public class Access 
    extends Base
{
    public final static syntelos.iou.dom.Name NAME = new syntelos.iou.dom.impl.Name(ELEMENT_NODE,"http://www.syntelos.org/xb","xb:access");

    public final static short PUBLIC       = 0x0001;
    public final static short PRIVATE      = 0x0002;
    public final static short PROTECTED    = 0x0004;
    public final static short STATIC       = 0x0008;
    public final static short FINAL        = 0x0010;
    public final static short SUPER        = 0x0020;
    public final static short SYNCHRONIZED = 0x0020;
    public final static short VOLATILE     = 0x0040;
    public final static short BRIDGE       = 0x0040;
    public final static short TRANSIENT    = 0x0080;
    public final static short VARARGS      = 0x0080;
    public final static short NATIVE       = 0x0100;
    public final static short INTERFACE    = 0x0200;
    public final static short ABSTRACT     = 0x0400;
    public final static short STRICT       = 0x0800;
    public final static short SYNTHETIC    = 0x1000;
    public final static short ANNOTATION   = 0x2000;
    public final static short ENUM         = 0x4000;

    public final static short CLASS_MODIFIERS  = (short)(PUBLIC|FINAL|STATIC|SUPER|INTERFACE|ABSTRACT|SYNTHETIC|ANNOTATION|ENUM);

    public final static short FIELD_MODIFIERS  = (short)(PUBLIC|PRIVATE|PROTECTED|STATIC|FINAL|VOLATILE|TRANSIENT|SYNTHETIC|ENUM);

    public final static short METHOD_MODIFIERS = (short)(PUBLIC|PRIVATE|PROTECTED|STATIC|FINAL|SYNCHRONIZED|BRIDGE|VARARGS|NATIVE|ABSTRACT|STRICT|SYNTHETIC);
    
    private final static syntelos.iou.objmap dict = new syntelos.iou.objmap();
    static {
        dict.put("public",new java.lang.Integer(PUBLIC));
        dict.put("private",new java.lang.Integer(PRIVATE));
        dict.put("protected",new java.lang.Integer(PROTECTED));
        dict.put("static",new java.lang.Integer(STATIC));
        dict.put("final",new java.lang.Integer(FINAL));
        dict.put("super",new java.lang.Integer(SUPER));
        dict.put("synchronized",new java.lang.Integer(SYNCHRONIZED));
        dict.put("volatile",new java.lang.Integer(VOLATILE));
        dict.put("bridge",new java.lang.Integer(BRIDGE));
        dict.put("transient",new java.lang.Integer(TRANSIENT));
        dict.put("varargs",new java.lang.Integer(VARARGS));
        dict.put("native",new java.lang.Integer(NATIVE));
        dict.put("interface",new java.lang.Integer(INTERFACE));
        dict.put("abstract",new java.lang.Integer(ABSTRACT));
        dict.put("strict",new java.lang.Integer(STRICT));
        dict.put("synthetic",new java.lang.Integer(SYNTHETIC));
        dict.put("annotation",new java.lang.Integer(ANNOTATION));
        dict.put("enum",new java.lang.Integer(ENUM));
    }
    /**
     * @param name Lookup one name
     * @return Access flags bit mask for modifier
     */
    public final static int Flag(java.lang.String name){
        java.lang.Integer re = (java.lang.Integer)dict.get(name);
        if (null != re)
            return re.intValue();
        else
            throw new Error.State("Unrecognized access modifier '"+name+"'.");
    }
    
    /**
     * <p> Access flags string. </p>
     */
    public static abstract class String
        extends syntelos.iou.chbuf
    {
        /**
         * <p> Class access flags string. </p>
         */
        public final static class Class 
            extends String
        {
            public Class(java.lang.String flags){
                super(flags);
            }
            public Class(int flags){
                super(flags);
            }
            public syntelos.iou.chbuf append(int flag){
                switch (flag){
                case PUBLIC:
                    this.append("public");
                    return this;
                case FINAL:
                    this.append("final");
                    return this;
                case STATIC:
                    this.append("static");
                    return this;
                case SUPER:
                    this.append("super");
                    return this;
                case INTERFACE:
                    this.append("interface");
                    return this;
                case ABSTRACT:
                    this.append("abstract");
                    return this;
                case SYNTHETIC:
                    this.append("synthetic");
                    return this;
                case ANNOTATION:
                    this.append("annotation");
                    return this;
                case ENUM:
                    this.append("enum");
                    return this;
                default:
                    return this;
                }
            }
        }
        /**
         * <p> Method access flags string. </p>
         */
        public final static class Method
            extends String
        {
            public Method(java.lang.String flags){
                super(flags);
            }
            public Method(int flags){
                super(flags);
            }
            public syntelos.iou.chbuf append(int flag){
                switch (flag){
                case PUBLIC:
                    this.append("public");
                    return this;
                case PRIVATE:
                    this.append("private");
                    return this;
                case PROTECTED:
                    this.append("protected");
                    return this;
                case FINAL:
                    this.append("final");
                    return this;
                case STATIC:
                    this.append("static");
                    return this;
                case SYNCHRONIZED:
                    this.append("synchronized");
                    return this;
                case BRIDGE:
                    this.append("bridge");
                    return this;
                case VARARGS:
                    this.append("varargs");
                    return this;
                case NATIVE:
                    this.append("native");
                    return this;
                case ABSTRACT:
                    this.append("abstract");
                    return this;
                case STRICT:
                    this.append("strict");
                    return this;
                case SYNTHETIC:
                    this.append("synthetic");
                    return this;
                default:
                    return this;
                }
            }
        }
        /**
         * <p> Field access flags string. </p>
         */
        public final static class Field
            extends String
        {
            public Field(java.lang.String flags){
                super(flags);
            }
            public Field(int flags){
                super(flags);
            }
            public syntelos.iou.chbuf append(int flag){
                switch (flag){
                case PUBLIC:
                    this.append("public");
                    return this;
                case PRIVATE:
                    this.append("private");
                    return this;
                case PROTECTED:
                    this.append("protected");
                    return this;
                case FINAL:
                    this.append("final");
                    return this;
                case STATIC:
                    this.append("static");
                    return this;
                case VOLATILE:
                    this.append("volatile");
                    return this;
                case TRANSIENT:
                    this.append("transient");
                    return this;
                case ENUM:
                    this.append("enum");
                    return this;
                case SYNTHETIC:
                    this.append("synthetic");
                    return this;
                default:
                    return this;
                }
            }
        }

        public final int flags;
	
        public String(java.lang.String modifiers){
            super(modifiers);
            java.util.StringTokenizer strtok = new java.util.StringTokenizer(modifiers," \t\r\n");
            java.lang.String token;
            int flags = 0;
            while (strtok.hasMoreTokens()){
                token = strtok.nextToken();
                flags |= Flag(token);
            }
            this.flags = flags;
        }
        public String(int flags){
            super();
            this.flags = flags;
            int mask = PUBLIC, test;
            while (mask <= ENUM){
                test = (flags & mask);
                if (0 != test)
                    this.append(test);
                mask <<= 1;
            }
        }
        public abstract syntelos.iou.chbuf append(int flag);

        public syntelos.iou.chbuf append(java.lang.String name){
            if (0 < this.length())
                super.append(' ');
            return super.append(name);
        }
        public int getFlags(){
            return this.flags;
        }
    }
    

    public Access(org.w3c.dom.Document doc, syntelos.iou.dom.Name name){
        super(doc,name);
    }
    public Access(org.w3c.dom.Document doc){
        this(doc,NAME);
    }
    public Access(){
        this(DOC_NIL);
    }

    public boolean isStatic(){
        return (STATIC == (this.getFlags() & STATIC));
    }
    public boolean isPrivate(){
        return (PRIVATE == (this.getFlags() & PRIVATE));
    }
    public boolean isProtected(){
        return (PROTECTED == (this.getFlags() & PROTECTED));
    }
    public boolean isPublic(){
        return (PUBLIC == (this.getFlags() & PUBLIC));
    }
    public boolean isInterface(){
        return (INTERFACE == (this.getFlags() & INTERFACE));
    }

    public void setFlags(int flags){
        java.lang.String value;
        org.w3c.dom.Node parent = this.getParentNode();
        if (parent instanceof Field)
            value = new String.Field(flags).toString();

        else if (parent instanceof Method)
            value = new String.Method(flags).toString();
        else
            /*
             * Includes xb.at.InnerClasses$Info
             */
            value = new String.Class(flags).toString();

        this.setChildData(value,this);
    }
    public int getFlags(){
        java.lang.String value = (java.lang.String)this.getChildData(IO.Data.STRING,this);
        org.w3c.dom.Node parent = this.getParentNode();
        if (parent instanceof Field)
            return new String.Field(value).getFlags();

        else if (parent instanceof Method)
            return new String.Method(value).getFlags();
        else
            /*
             * Includes xb.at.InnerClasses$Info
             */
            return new String.Class(value).getFlags();
    }

    public void readCF(IO.Uri src, CF.Reader reader)
        throws java.io.IOException
    {
        int flags = reader.readUnsignedShort();
        this.setFlags(flags);
    }
    public void writeCF(IO.Uri src, CF.Writer writer)
        throws java.io.IOException
    {
        int flags = this.getFlags();
        writer.writeShort(flags);
    }
}
